
import re, warnings, multiprocessing, time, struct
import math

class CmdMessenger:
    """
    Basic interface for interfacing over a serial connection to an arduino
    using the CmdMessenger library.
    """

    def __init__(self,
                 mode,
                 board_instance,
                 commands,
                 field_separator=",",
                 command_separator=";",
                 escape_separator="/",
                 warnings=True):
        """
        Input:
            board_instance:
                instance of ArduinoBoard initialized with correct serial
                connection (points to correct serial with correct baud rate) and
                correct board parameters (float bytes, etc.)

            commands:
                a list or tuple of commands specified in the arduino .ino file
                *in the same order* they are listed there.  commands should be
                a list of lists, where the first element in the list specifies
                the command name and the second the formats for the arguments.
                (e.g. commands = [["who_are_you",""],["my_name_is","s"]])

            field_separator:
                character that separates fields within a message
                Default: ","

            command_separator:
                character that separates messages (commands) from each other
                Default: ";"

            escape_separator:
                escape character to allow separators within messages.
                Default: "/"

            warnings:
                warnings for user
                Default: True

            The separators and escape_separator should match what's
            in the arduino code that initializes the CmdMessenger.  The default
            separator values match the default values as of CmdMessenger 4.0.
        """

        self.commands = commands[:]
        self.field_separator = field_separator
        self.command_separator = command_separator
        self.escape_separator = escape_separator
        self.give_warnings = warnings

        self._cmd_name_to_int = {}
        self._int_to_cmd_name = {}
        self._cmd_name_to_format = {}
        for i, c in enumerate(commands):
            self._cmd_name_to_int[c[0]] = i
            self._int_to_cmd_name[i] = c[0]
            self._cmd_name_to_format[c[0]] = c[1]

        self._byte_field_sep = self.field_separator.encode("ascii")
        self._byte_command_sep = self.command_separator.encode("ascii")
        self._byte_escape_sep = self.escape_separator.encode("ascii")
        self._escaped_characters = [self._byte_field_sep,
                                    self._byte_command_sep,
                                    self._byte_escape_sep,
                                    b'\0']

        self._null_escape_re = re.compile(b'\0')
        self._escape_re = re.compile("([{}{}{}\0])".format(self.field_separator,
                                                           self.command_separator,
                                                           self.escape_separator).encode('ascii'))

        self._send_methods = {"c":self._send_char,
                              "b":self._send_byte,
                              "i":self._send_int,
                              "I":self._send_unsigned_int,
                              "l":self._send_long,
                              "L":self._send_unsigned_long,
                              "f":self._send_float,
                              "d":self._send_double,
                              "s":self._send_string,
                              "?":self._send_bool,
                              "g":self._send_guess}

        self._recv_methods = {"c":self._recv_char,
                              "b":self._recv_byte,
                              "i":self._recv_int,
                              "I":self._recv_unsigned_int,
                              "l":self._recv_long,
                              "L":self._recv_unsigned_long,
                              "e": self._recv_sci_float,
                              "f":self._recv_float,
                              "d":self._recv_double,
                              "s":self._recv_string,
                              "?":self._recv_bool,
                              "g":self._recv_guess}


    def send(self,cmd,*args,arg_formats=None):
        """
        Send a command (which may or may not have associated arguments) to an
        arduino using the CmdMessage protocol.  The command and any parameters
        should be passed as direct arguments to send.

        arg_formats is an optional string that specifies the formats to use for
        each argument when passed to the arduino. If specified here,
        arg_formats supercedes formats specified on initialization.
        """

        # Turn the command into an integer.
        try:
            command_as_int = self._cmd_name_to_int[cmd]
        except KeyError:
            err = "Command '{}' not recognized.\n".format(cmd)
            raise ValueError(err)

        # Figure out what formats to use for each argument.
        arg_format_list = []
        if arg_formats != None:

            # The user specified formats
            arg_format_list = list(arg_formats)

        else:
            try:
                # See if class was initialized with a format for arguments to this
                # command
                arg_format_list = self._cmd_name_to_format[cmd]
            except KeyError:
                # if not, guess for all arguments
                arg_format_list = ["g" for i in range(len(args))]

        # Deal with "*" format
        arg_format_list = self._treat_star_format(arg_format_list,args)

        if len(args) > 0:
            if len(arg_format_list) != len(args):
                err = "Number of argument formats must match the number of arguments."
                raise ValueError(err)

        # Go through each argument and create a bytes representation in the
        # proper format to send.  Escape appropriate characters.
        fields = ["{}".format(command_as_int).encode("ascii")]
        for i, a in enumerate(args):
            fields.append(self._send_methods[arg_format_list[i]](a))
            fields[-1] = self._escape_re.sub(self._byte_escape_sep + r"\1".encode("ascii"),fields[-1])

        # Make something that looks like cmd,field1,field2,field3;
        compiled_bytes = self._byte_field_sep.join(fields) + self._byte_command_sep
        #print(compiled_bytes)
        # Send the message.
        # self.board.write(compiled_bytes)
        # self.board.flush()
        return compiled_bytes

    def _treat_star_format(self,arg_format_list,args):
        """
        Deal with "*" format if specified.
        """

        num_stars = len([a for a in arg_format_list if a == "*"])
        if num_stars > 0:

            # Make sure the repeated format argument only occurs once, is last,
            # and that there is at least one format in addition to it.
            if num_stars == 1 and arg_format_list[-1] == "*" and len(arg_format_list) > 1:

                # Trim * from end
                arg_format_list = arg_format_list[:-1]

                # If we need extra arguments...
                if len(arg_format_list) < len(args):
                    f = arg_format_list[-1]
                    len_diff = len(args) - len(arg_format_list)
                    tmp = list(arg_format_list)
                    tmp.extend([f for i in range(len_diff)])
                    arg_format_list = "".join(tmp)
            else:
                err = "'*' format must occur only once, be at end of string, and be preceded by at least one other format."
                raise ValueError(err)

        return arg_format_list

    def _send_char(self,value):
        """
        Convert a single char to a bytes object.
        """

        if type(value) != str and type(value) != bytes:
            err = "char requires a string or bytes array of length 1"
            raise ValueError(err)

        if len(value) != 1:
            err = "char must be a single character, not \"{}\"".format(value)
            raise ValueError(err)

        if type(value) != bytes:
            value = value.encode("ascii")

        if value in self._escaped_characters:
            err = "Cannot send a control character as a single char to arduino.  Send as string instead."
            raise OverflowError(err)

        return struct.pack('c',value)

    def _send_byte(self,value):
        """
        Convert a numerical value into an integer, then to a byte object. Check
        bounds for byte.
        """

        # Coerce to int. This will throw a ValueError if the value can't
        # actually be converted.
        if type(value) != int:
            new_value = int(value)

            if self.give_warnings:
                w = "Coercing {} into int ({})".format(value,new_value)
                warnings.warn(w,Warning)
                value = new_value

        # Range check
        if value > 255 or value < 0:
            err = "Value {} exceeds the size of the board's byte.".format(value)
            raise OverflowError(err)

        return struct.pack("B",value)

    def _send_int(self,value):
        """
        Convert a numerical value into an integer, then to a bytes object Check
        bounds for signed int.
        """

        # Coerce to int. This will throw a ValueError if the value can't
        # actually be converted.
        if type(value) != int:
            new_value = int(value)

            if self.give_warnings:
                w = "Coercing {} into int ({})".format(value,new_value)
                warnings.warn(w,Warning)
                value = new_value

        return struct.pack("h",value)

    def _send_unsigned_int(self,value):
        """
        Convert a numerical value into an integer, then to a bytes object. Check
        bounds for unsigned int.
        """
        # Coerce to int. This will throw a ValueError if the value can't
        # actually be converted.
        if type(value) != int:
            new_value = int(value)

            if self.give_warnings:
                w = "Coercing {} into int ({})".format(value,new_value)
                warnings.warn(w,Warning)
                value = new_value

        # Range check
        # if value > self.board.unsigned_int_max or value < self.board.unsigned_int_min:
        #     err = "Value {} exceeds the size of the board's unsigned int.".format(value)
        #     raise OverflowError(err)

        return struct.pack("H",value)

    def _send_long(self,value):
        """
        Convert a numerical value into an integer, then to a bytes object. Check
        bounds for signed long.
        """

        # Coerce to int. This will throw a ValueError if the value can't
        # actually be converted.
        if type(value) != int:
            new_value = int(value)

            if self.give_warnings:
                w = "Coercing {} into int ({})".format(value,new_value)
                warnings.warn(w,Warning)
                value = new_value

        # Range check
        if value > self.board.long_max or value < self.board.long_min:
            err = "Value {} exceeds the size of the board's long.".format(value)
            raise OverflowError(err)

        return struct.pack("i",value)

    def _send_unsigned_long(self,value):
        """
        Convert a numerical value into an integer, then to a bytes object.
        Check bounds for unsigned long.
        """

        # Coerce to int. This will throw a ValueError if the value can't
        # actually be converted.
        if type(value) != int:
            new_value = int(value)

            if self.give_warnings:
                w = "Coercing {} into int ({})".format(value,new_value)
                warnings.warn(w,Warning)
                value = new_value

        # Range check
        if value > self.board.unsigned_long_max or value < self.board.unsigned_long_min:
            err = "Value {} exceeds the size of the board's unsigned long.".format(value)
            raise OverflowError(err)

        return struct.pack("I",value)

    def _send_float(self,value):
        """
        Return a float as a IEEE 754 format bytes object.
        """

        # convert to float. this will throw a ValueError if the type is not
        # readily converted
        if type(value) != float:
            value = float(value)

        # Range check
        if value > self.board.float_max or value < self.board.float_min:
            err = "Value {} exceeds the size of the board's float.".format(value)
            raise OverflowError(err)

        return struct.pack("f",value)

    def _send_double(self,value):
        """
        Return a float as a IEEE 754 format bytes object.
        """

        # convert to float. this will throw a ValueError if the type is not
        # readily converted
        if type(value) != float:
            value = float(value)

        # Range check
        if value > self.board.float_max or value < self.board.float_min:
            err = "Value {} exceeds the size of the board's float.".format(value)
            raise OverflowError(err)

        return struct.pack("self.board.double_type",value)

    def _send_string(self,value):
        """
        Convert a string to a bytes object.  If value is not a string, it is
        be converted to one with a standard string.format call.
        """

        if type(value) != bytes:
            value = "{}".format(value).encode("ascii")

        return value

    def _send_bool(self,value):
        """
        Convert a boolean value into a bytes object.  Uses 0 and 1 as output.
        """

        # Sanity check.
        if type(value) != bool and value not in [0,1]:
            err = "{} is not boolean.".format(value)
            raise ValueError(err)

        return struct.pack("?",value)

    def _send_guess(self,value):
        """
        Send the argument as a string in a way that should (probably, maybe!) be
        processed properly by C++ calls like atoi, atof, etc.  This method is
        NOT RECOMMENDED, particularly for floats, because values are often
        mangled silently.  Instead, specify a format (e.g. "f") and use the
        CmdMessenger::readBinArg<CAST> method (e.g. c.readBinArg<float>();) to
        read the values on the arduino side.
        """

        if type(value) != str and type(value) != bytes and self.give_warnings:
            w = "Warning: Sending {} as a string. This can give wildly incorrect values. Consider specifying a format and sending binary data.".format(value)
            warnings.warn(w,Warning)

        if type(value) == float:
            return "{:.10e}".format(value).encode("ascii")
        elif type(value) == bool:
            return "{}".format(int(value)).encode("ascii")
        else:
            return self._send_string(value)

    def  _receive_one_field( self ):

        # Read serial input until a command separator or empty character is
        # reached
        escaped = False
        command_sep_found = False
        one_field = []
        timeout = False
        while True:

            tmp = self.board.read()
            #raw_msg.append(tmp)
            if tmp == b'':
                timeout = True
                break

            if escaped:

                # Either drop the escape character or, if this wasn't really
                # an escape, keep previous escape character and new character
                if tmp in self._escaped_characters:
                    one_field.append(tmp)
                    escaped = False
                else:
                    one_field.append(self._byte_escape_sep)
                    one_field.append(tmp)
                    escaped = False
            else:

                # look for escape character
                if tmp == self._byte_escape_sep:
                    escaped = True
                    #print("escaped = True")

                # or field separator
                elif tmp == self._byte_field_sep:
                    #msg.append([])
                    #print(one_field)
                    break

                # or command separator
                elif tmp == self._byte_command_sep:
                    command_sep_found = True
                    #print(command_sep_found)
                    break

                # or any empty characater 表示timeout退出
                elif tmp == b'':
                    #print("tmp == b''")
                    break

                # okay, must be something
                else:
                    one_field.append(tmp)
                    #print("else")
                    #print(one_field)

        zzfield = b''.join(one_field)
        return  zzfield , timeout

        #直到找到;符号
    """
    def _clear_receiver_buff( self):  
        num_clear = 0
        num_print = 100
        #正确接收后，buffer内不会有数据，如果有，肯定是有错位问题
        rev_num = self.board.inWaiting()
        if rev_num == 0:
            return
        #print("try clear rev buffer " + str(rev_num))        
        while True:
            #还要考虑没有新数据
            tmp = self.board.read()
            print(tmp)
            if tmp == ';' :
                print("find end, clear rev buffer " + str(num_clear)) 
                break;
            num_clear = num_clear +1
            #num_print = num_print -1
            #if num_print > 0:
            #    print(tmp)
    """
    """            
    def _clear_receiver_buff( self):  
        num_print = 100
        rev_num = self.board.inWaiting()
        print("try clear rev buffer " + str(rev_num))        
        while rev_num >0:
            #还要考虑没有新数据
            tmp = self.board.read()
            
            num_print = num_print -1
            if num_print > 0:
                print(tmp)
    """

    #检查结束是不是;号，是的话，返回确认包，不是的话，多读几次直到找到;号，
    #正常结束的话，最后一个float field是;结束的，所以可能串口会读不到新的数据
    """
    def  _check_packet_receive_end( self, total_recv ):

    # Read serial input until a command separator or empty character is
        # reached 
        #escaped = False
        command_sep_found = False        
        #one_field = []
        rev_num = self.board.inWaiting()
        print("rev buffer " + str(rev_num))
        if rev_num == 0:
            #返回正确确认包，
            print("send kConfirm " + str(total_recv))
            self.send("kConfirm",total_recv) 
            return
            
        while rev_num >0:
            #还要考虑没有新数据
            tmp = self.board.read()
            print(tmp)
            #raw_msg.append(tmp)
            if tmp == self._byte_command_sep:
                command_sep_found = True
                break
            else:
                rev_num = rev_num - 1
                if  rev_num == 0 :
                    break
                
        if command_sep_found == True :
            #返回正确确认包，
            print("send kConfirm " + str(total_recv))
            self.send("kConfirm",total_recv) 
        else:
            #返回错误确认包
            print("send kConfirm " + str(0))
            self.send("kConfirm",0) 
    """

    #出现“UnicodeDecodeError: 'utf-8' codec can't decode byte 0xaa in position 1: invalid start byte”是因为插入了干扰数据，所以计数满了后，需要再尝试把buffer清空
    def _recv_float_array_with_indx(self, packet_lens ):
        """
        Recieve a long in binary format, returning as python int.
        """
        status = 0
        error = 0
        rec_count = 0;
        bak_packet_lens = packet_lens/3
        bak_indx = 0
        self.tx_current =[]
        self.rx_voltage =[]
        self.tx_voltage =[]
        #/* 这里发送一个cmd的结束符，后续发数据，又会先发送一个"，" ，这样形成一个空字符, 没必要处理，上层滤掉就行*/
        #这里会读到一个空字符，原因是上面解释，多读一次去掉就行
        #str_one_field = self._receive_one_field()
        #if str_one_field == b'':
        #    print(" get null ")
        #print("unused:")
        #print(str_one_field)
        while True:
            error = 0
            #接收包头AA55
            str_one_field , timeout = self._receive_one_field()
            if timeout == True:
                error = error + 1
                break
            str_lens =  len(str_one_field)
            if str_one_field == b'':
                continue
            elif str_lens < 2:
                print("header len error " + str(str_one_field))
                print("last indx= " + str( bak_indx ))
                continue
            elif str_lens > 2:
                error = error + 1
                print("header len >4, break: " + str(str_one_field))
                break
            else:
                header = self._recv_unsigned_int(str_one_field)
                #print(header)
                if header != 0xAA55:
                    print("header error " + str(str_one_field))
                    continue
            #接收包的indx
            #需要对接收到的_receive_one_field的长度做判断，如果长度不够，就认为接收出错
            str_one_field , timeout = self._receive_one_field()
            if timeout == True:
                error = error + 1
                break
            str_lens =  len(str_one_field)

            if str_lens != 2:
                error = error + 1
                print("error: " + str(str_one_field))
                break
            else:
                indx = self._recv_unsigned_int(str_one_field)
                bak_indx = indx
                if  indx > bak_packet_lens:
                    error = error + 1
                    print(str_one_field)
                    print("error indx= " + str(indx) + ", packet_len= " + str(bak_packet_lens))
                    break

            str_one_field , timeout = self._receive_one_field()
            if timeout == True:
                error = error + 1
                break
            #print(str_one_field)
            str_lens =  len(str_one_field)
            #print(str_lens)
            if str_lens != 4:
                error = error + 1
                print(str(indx) + " indx, error when tx_voltage, break  " )
                print(str_one_field)
                break
            else:
                tx_voltage_data = self._recv_float(str_one_field)
                #print(data)


            str_one_field , timeout = self._receive_one_field()
            if timeout == True:
                error = error + 1
                break
            #print(str_one_field)
            str_lens =  len(str_one_field)
            #print(str_lens)
            if str_lens != 4:
                error = error + 1
                print(str(indx) + " indx, error when tx_current , break " )
                print(str_one_field)
                break
            else:
                tx_current_data = self._recv_float(str_one_field)
                #print(data)

            str_one_field , timeout = self._receive_one_field()
            if timeout == True:
                error = error + 1
                break
            #print(str_one_field)
            str_lens =  len(str_one_field)
            #print(str_lens)
            if str_lens != 4:
                error = error + 1
                print(str(indx) + " indx, error when rx_voltage , break" )
                print(str_one_field)
                break
            else:
                rx_voltage_data = self._recv_float(str_one_field)
                #print(data)

            #if error == 0:
            #反馈ack，正确的话，内容就是indx，错误的话，不返回任何信息
            #print("ack:" + str(indx) )
            #self.send("kConfirm",indx)
            rec_count = rec_count + 1

            self.tx_voltage.append (tx_voltage_data )
            self.tx_current.append (tx_current_data )
            self.rx_voltage.append (rx_voltage_data )

            packet_lens = packet_lens - 3
            if(packet_lens <= 0 ):
                print("avaid received len: " + str( rec_count ))
                print("tx_v len: " + str( len(self.tx_voltage ) ) + ", tx_c len: " + str( len(self.tx_current ) ) + ", rx_v len: " + str( len(self.rx_voltage ) ))

                if bak_packet_lens == rec_count:
                    #返回正确确认包，
                    #self._clear_receiver_buff()
                    print("send kConfirm " + str(rec_count))
                    self.send("kConfirm",rec_count)
                    status = 0
                else:
                    #返回出错确认包，
                    #self._clear_receiver_buff()
                    print("error, send kConfirm " + str(0))
                    self.send("kConfirm",0)
                    #self._clear_receiver_buff()
                    status = 1
                break

        if error > 0 :
            status = 1
        #检查是不是接收到;号，表述传输结束了
        #self._check_packet_receive_end( rec_count )

        return status, self.tx_current, self.rx_voltage, self.tx_voltage
    """    
    def _recv_float_array(self, packet_lens ):
        ""
        #Recieve a long in binary format, returning as python int.
        ""
        self.tx_current =[]
        self.rx_voltage =[]
        self.tx_voltage =[]
        str_one_field = self._receive_one_field()
        while True:
            str_one_field = self._receive_one_field()
            #print(str_one_field)
            data = self._recv_float(str_one_field)
            #print(data)
            self.tx_voltage.append (data )

            str_one_field = self._receive_one_field()
            #print(str_one_field)
            data = self._recv_float(str_one_field)
            #print(data)
            self.tx_current.append (data )

            str_one_field = self._receive_one_field()
            #print(str_one_field)
            data = self._recv_float(str_one_field)
            #print(data)
            self.rx_voltage.append (data )

            packet_lens = packet_lens - 3
            if(packet_lens <= 0 ):
                #print("packet load rec done...")
                break;
        return self.tx_current, self.rx_voltage, self.tx_voltage
    """
    """    
    def _recv_sci_float_array(self, packet_lens ):
        ""
        Recieve a long in binary format, returning as python int.
        ""
        self.tx_current =[]
        self.rx_voltage =[]
        self.tx_voltage =[]
        while True:
            data = self.board.read_num(12)
            #print(data[1:])
            vvv = data[1:]
            float_str = str(vvv).strip("b'").strip("'")
            #print(float_str)
            value = self.sci_to_float(float_str)   
            #value,  = struct.unpack('f', data)
            self.tx_voltage.append (value )
            #packet_lens = packet_lens - 4
            
            data = self.board.read_num(12)
            vvv = data[1:]
            float_str = str(vvv).strip("b'").strip("'")
            #print(float_str)
            value = self.sci_to_float(float_str)   
            #value,  = struct.unpack('f', data)
            self.tx_current.append (value )
            #packet_lens = packet_lens - 4
            
            data = self.board.read_num(12)
            vvv = data[1:]
            float_str = str(vvv).strip("b'").strip("'")
            #print(float_str)
            value = self.sci_to_float(float_str)   
            #value,  = struct.unpack('f', data)
            self.rx_voltage.append (value )
            packet_lens = packet_lens - 3
            #print(packet_lens)
            
            if(packet_lens <= 0 ):
                #print("packet load rec done...")
                break;
        return self.tx_current, self.rx_voltage, self.tx_voltage
    """


    def sci_to_float(self,str_num):
        #print(str_num)
        before_e = float(str_num.split('E')[0])
        sign = str_num.split('E')[1][:1]
        after_e = int(str_num.split('E')[1][1:])

        if sign == '+':
            float_num = before_e * math.pow(10, after_e)
        elif sign == '-':
            float_num = before_e * math.pow(10, -after_e)
        else:
            float_num = None
            print('error: unknown sign')
        return float_num

    def _recv_sci_float(self,value):
        """
        Recieve a float in binary format, returning as python float.
        """
        #print(value)
        float_str = str(value).strip("b'").strip("'")
        #print(float_str)
        return self.sci_to_float(float_str)

    def _recv_char(self,value):
        """
        Recieve a char in binary format, returning as string.
        """

        return struct.unpack("c",value)[0].decode("ascii")

    def _recv_byte(self,value):
        """
        Recieve a byte in binary format, returning as python int.
        """

        return struct.unpack("B",value)[0]

    def _recv_int(self,value):
        """
        Recieve an int in binary format, returning as python int.
        """
        return struct.unpack(self.board.int_type,value)[0]

    def _recv_unsigned_int(self,value):
        """
        Recieve an unsigned int in binary format, returning as python int.
        """

        return struct.unpack(self.board.unsigned_int_type,value)[0]

    def _recv_long(self,value):
        """
        Recieve a long in binary format, returning as python int.
        """
        #print(value)
        long_str = str(value).strip("b'").strip("'")
        #print(long_str)
        return int(long_str)

        #def _recv_long(self,value):
        """
        Recieve a long in binary format, returning as python int.
        """

    #    return struct.unpack(self.board.long_type,value)[0]

    def _recv_unsigned_long(self,value):
        """
        Recieve an unsigned long in binary format, returning as python int.
        """

        return struct.unpack(self.board.unsigned_long_type,value)[0]

    def _recv_float(self,value):
        """
        Recieve a float in binary format, returning as python float.
        """

        return struct.unpack(self.board.float_type,value)[0]

    def _recv_double(self,value):
        """
        Recieve a double in binary format, returning as python float.
        """

        return struct.unpack(self.board.double_type,value)[0]

    def _recv_string(self,value):
        """
        Recieve a binary (bytes) string, returning a python string.
        """

        s = value.decode('ascii')

        # Strip null characters
        s = s.strip("\x00")

        # Strip other white space
        s = s.strip()

        return s

    def _recv_bool(self,value):
        """
        Receive a binary bool, return as python bool.
        """

        return struct.unpack("?",value)[0]

    def _recv_guess(self,value):
        """
        Take the binary spew and try to make it into a float or integer.  If
        that can't be done, return a string.

        Note: this is generally a bad idea, as values can be seriously mangled
        by going from float -> string -> float.  You'll generally be better off
        using a format specifier and binary argument passing.
        """

        if self.give_warnings:
            w = "Warning: Guessing input format for {}. This can give wildly incorrect values. Consider specifying a format and sending binary data.".format(value)
            warnings.warn(w,Warning)

        tmp_value = value.decode()

        try:
            float(tmp_value)

            if len(tmp_value.split(".")) == 1:
                # integer
                return int(tmp_value)
            else:
                # float
                return float(tmp_value)

        except ValueError:
            pass

        # Return as string
        return self._recv_string(value)


